#include "model/model.h"
#include "model/animatedmodel.h"

namespace sheeplib {

	namespace model {
		
		int AnimatedModel::FindAnimation(const string& name) const {
			vector<ModelAnimation>::const_iterator it(std::find_if(m_Animations.begin(), m_Animations.end(), Finder(name) ));

			if (it == m_Animations.end())
				return -1;
			else
				return (int) std::distance(m_Animations.begin(), it);
		}
				
		bool AnimatedModel::LoadAnimationFile(const string& filename) {
			assert (m_FPS > 0); //If not you should be calling SetFPS() in the subclass!

			m_Animations.clear();

			ifstream fileIn(filename.c_str());
			string line;

			if (!fileIn.is_open()) {
				SetErrorString("Could not load animation file: " + filename);
				return false;
			}

			while (fileIn.good())
			{
				getline(fileIn, line);

				stringstream linestream(line);

				int frame1, frame2;
				string name;

				linestream >> frame1 >> frame2 >> name;

				ModelAnimation anim;
				anim.m_StartTime = frame1 / m_FPS;
				anim.m_EndTime = frame2 / m_FPS;
				anim.m_Name = name;

				m_Animations.push_back(anim);
			}

			fileIn.close();

			return true;
		}
		
		void AnimatedModel::SetAnimationTime(float time) {
			m_CurrentAnimationTime = time;
		}

		ModelFrame& AnimatedModel::GetInterpolatedFrame() {
			return m_InterpolatedFrame;
		}

		const ModelFrame& AnimatedModel::GetInterpolatedFrame() const {
			return m_InterpolatedFrame;
		}
		
		const float AnimatedModel::GetAnimTime() const {
			return m_CurrentAnimationTime;
		}

		void AnimatedModel::SetAnimation(const string& name) {
			if (m_Animations.empty())
				return;

			int anim = FindAnimation(name);

			if (anim == -1)
				throw std::out_of_range("Animation not found: " + name);


			m_CurrentAnimation = name;
			m_NextAnimation = name;

			m_CurrentAnimationTime = m_Animations[anim].m_StartTime;
			m_CurrentAnimationEndTime = m_Animations[anim].m_EndTime;
		}

		void AnimatedModel::SetNextAnimation(const string& name) {
			if (m_Animations.empty())
				return;

			int id = FindAnimation(name);

			if (id == -1) {
				throw std::logic_error("Attempted to set invalid animation");
			}

			assert(id < (int) m_Animations.size());

			m_NextAnimation = m_Animations[id].m_Name;
		}

		void AnimatedModel::MoveNextAnimation() {
			if (m_Animations.empty())
				return;

			m_CurrentAnimation = m_NextAnimation;

			int anim = FindAnimation(m_CurrentAnimation);
			m_CurrentAnimationTime = m_Animations[anim].m_StartTime;
			m_CurrentAnimationEndTime = m_Animations[anim].m_EndTime;
		}

		const string AnimatedModel::GetCurrentAnimation() const {
			return m_CurrentAnimation;
		}

		void AnimatedModel::SetFPS(float v) {
			m_FPS = v;
		}

		const float AnimatedModel::GetAnimEndTime() const {
			return m_CurrentAnimationEndTime;
		}

		vector<ModelAnimation>& AnimatedModel::GetAnimations() {
			return m_Animations;
		}

		void AnimatedModel::IncrementCurrentAnimationTime(float dT) {
			m_CurrentAnimationTime += dT;
		}
		
		///Returns a list of the possible animations that can be set
		const vector<string> AnimatedModel::slListAnimations() const {
			vector<string> anims;
			for (vector<ModelAnimation>::const_iterator it = m_Animations.begin();
				it != m_Animations.end(); ++it) {
				
				anims.push_back((*it).m_Name);
			}
			
			return anims;
		}
			
		void AnimatedModel::slSetAnimation(const string& animationName) {
			SetAnimation(animationName);
		}
		
		void AnimatedModel::slSetNextAnimation(const string& animationName) {
			SetNextAnimation(animationName);
		}
		
		bool AnimatedModel::slLoadAnimationFile(const string& filename) {
			return LoadAnimationFile(filename);
		}
		
	}
}
